/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.classdiagram.figures;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.FreeformViewport;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.ScrollPane;
import org.eclipse.draw2d.StackLayout;
import org.eclipse.draw2d.ToolbarLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.NamedElement;

import com.cea.papyrus.core.figures.IAbstractElementFigure;
import com.cea.papyrus.core.figures.NodeFigure;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;

/**
 * Figure for a package element
 */
public class PackageFigure extends Figure implements IAbstractElementFigure {

	/** Debug channel */
	private final int debugChannel=6;

	/** Header figure that compose the package figure */
	protected final UMLPackageHeaderFigure headerFigure; //head of the package

	/** figure that contains the children elements of the package */
	protected final UMLPackageContentFigure contentFigure;	// content of the package

	/**
	 * Creates a new PackageFigure.
	 */
	public PackageFigure() {	
		setLayoutManager(new ToolbarLayout());
		headerFigure = new UMLPackageHeaderFigure();
		add(headerFigure);
		contentFigure =new UMLPackageContentFigure();
		add(contentFigure);	
		setOpaque(false);
	}
	
	/**
	 * Returns the header figure for the package figure.
	 * @return the header figure for the package figure.
	 */
	public NodeFigure getHeaderFigure() {
		return headerFigure;
	}

	/**
	 * Sets the border color of the figure.
	 * @param borderColor the color of the border of the figure
	 */
	public void setBorderColor(Color borderColor) {
		// delegates to the header and content figures
		headerFigure.setBorderColor(borderColor);
		contentFigure.setBorder(new LineBorder(borderColor));
	}

	/**
	 * Returns the border color.
	 * @returns the border color of the header figure
	 */
	public Color getBorderColor() {
		// delegates the color management to the header figure
		return headerFigure.getBorderColor();
	}

	/**
	 * Sets the background color.
	 * @param backgroundColor The new background color
	 */
	@Override
	public void setBackgroundColor(Color backgroundColor) {
		// delegates to the header and content figures
		headerFigure.setBackgroundColor(backgroundColor);
		contentFigure.setBackgroundColor(backgroundColor);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setForegroundColor(Color foregroundColor) {
		// delegates to the header and content figures
		headerFigure.setBackgroundColor(foregroundColor);
		contentFigure.setBackgroundColor(foregroundColor);
	}

	/**
	 * Returns the background color.
	 * @returns the background color of the header figure
	 */
	@Override
	public Color getBackgroundColor() {
		// delegates the color management to the header figure
		return headerFigure.getBackgroundColor();
	}

	/**
	 * setBound is called to resize or move graphical Element by Eclipse
	 * It calls setBound of each subFigure.
	 * In the case of contentPackage we call setDimension
	 * @param rect coordinate of the contentPackage.
	 * @see setDimension
	 */
	@Override
	public void setBounds(Rectangle rect) {
		headerFigure.setBounds(rect);
		contentFigure.setBounds(rect);
		super.setBounds(rect);
		Debug.debug(this," bounds are : " +getBounds(), debugChannel);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFont(Font f) {
		// delegates the font management to the header figure
		headerFigure.setFont(f);
	}

	/**
	 * Returns the ContentPane figure of the Content Figure
	 * @return the content pane of the content sub-figure
	 */
	public IFigure getContentPane() {
		return contentFigure.getContentPane();
	}

	/**
	 * Sets the new icon image
	 * @param img the image to display for this package figure
	 */
	public void setIcon(Image img) {
		headerFigure.setIcon(img);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected boolean useLocalCoordinates(){
		return true;
	}

	/**
	 * Returns the width of the header figure
	 * @return the width of the header figure
	 */
	public int getHeaderWitdh()  { 
		return headerFigure.getSize().width;
	}

	/**
	 * Returns the width of the header figure
	 * @return the width of the header figure
	 */
	public int getHeaderHeight() { 
		return headerFigure.getSize().height;
	}

	/**
	 * Returns the name label of the header figure
	 * @return the name label of the header figure
	 */
	public Label getNameLabel() {
		return headerFigure.getNameLabel();
	}

	/**
	 * Returns the qualified name label of the header figure
	 * @return the qualified name label of the header figure
	 */
	public Label getQualifiedNameLabel() {
		return headerFigure.getQualifiedNameLabel();
	}

	/**
	 * Returns the stereotype label of the header figure
	 * @return the stereotype label of the header figure
	 */
	public Label getStereotypesLabel() {
		return headerFigure.getStereotypesLabel();
	}

	/**
	 * Sets the text in the name label of the header figure name
	 * @param name the name of the represented element
	 */
	public void setName( String name ) {
		headerFigure.setName(name);
	}

	/**
	 * Sets the text in the qualified name label of the header figure name
	 * @param name the qualified name of the represented element
	 */
	public void setQualifiedName( String packageName ) {
		headerFigure.setQualifiedName(packageName);
	}

	/**
	 * Sets the text in the stereotype label of the header figure name
	 * @param name the stereotype of the represented element
	 */
	public void setStereotypes( String stereotypes ) {
		headerFigure.setStereotypes(stereotypes);
	}

	/**
	 * Refresh presentation of current figure with presentation specified in a GraphNode.
	 * @param presentation the new type of Presentation
	 * @param selection the selected UML Element
	 */
	public void refreshPresentation(String presentation, Element selection, GraphElement ge) {
		headerFigure.refreshPresentation(presentation, selection, ge);
	}

	/**
	 * Refresh list of stereotypes of current EditPart if required
	 * either with or without the first stereotype.
	 * @param presentation the kind of display
	 * @param hasIcon indicates if icon display is allowed
	 * @param hasShape indicates if shape form is allowed
	 * @param stereotypes the list of stereotypes to display
	 */
	public void refreshStereotypes(String stereotypes, String presentation, boolean hasIcon, boolean hasShape) {
		headerFigure.refreshStereotypes(stereotypes, presentation, hasIcon, hasShape);
	}

	/**
	 * {@inheritDoc}
	 */
	public Color getFontColor() {
		return headerFigure.getFontColor();
	}

	/**
	 * {@inheritDoc}
	 */
	public int getFontSize() {
		return headerFigure.getFontSize();
	}

	/**
	 * {@inheritDoc}
	 */
	public Color getForeGroundColor() {
		return headerFigure.getForeGroundColor();
	}

	/**
	 * {@inheritDoc}
	 */
	public Label getLabelAt(Point pt) {
		return headerFigure.getLabelAt(pt);
	}

	/**
	 * {@inheritDoc}
	 */
	public String getLineStle() {
		return headerFigure.getLineStle();
	}

	/**
	 * {@inheritDoc}
	 */
	public int getLineThickness() {
		return headerFigure.getLineThickness();
	}

	/**
	 * {@inheritDoc}
	 */
	public Dimension getMinimumDimension() {
		return headerFigure.getMinimumDimension();
	}

	/**
	 * {@inheritDoc}
	 */
	public String getfigureFont() {
		return headerFigure.getfigureFont();
	}

	/**
	 * {@inheritDoc}
	 */
	public void refreshColors(GraphElement graphelement) {
		headerFigure.refreshColors(graphelement);
		contentFigure.setBackgroundColor(headerFigure.getBackgroundColor());
		contentFigure.setFont(headerFigure.getFont());
		contentFigure.setBorder(headerFigure.getBorder());
	}

	/**
	 * {@inheritDoc}
	 */
	public void refreshQualifiedName(GraphElement parentge, GraphElement currentge, NamedElement element) {
		headerFigure.refreshQualifiedName(parentge, currentge, element);
	}

	/**
	 * {@inheritDoc}
	 */
	public void setFontColor(Color fontColor) {
		headerFigure.setFontColor(fontColor);
	}

	/**
	 * {@inheritDoc}
	 */
	public void setFontSize(int fontSize) {
		headerFigure.setFontSize(fontSize);
	}

	/**
	 * {@inheritDoc}
	 */
	public void setForeGroundColor(Color foreGroundColor) {
		headerFigure.setForeGroundColor(foreGroundColor);
	}

	/**
	 * {@inheritDoc}
	 */
	public void setLineStle(String lineStle) {
		headerFigure.setLineStle(lineStle);
	}

	/**
	 * {@inheritDoc}
	 */
	public void setLineThickness(int lineThickness) {
		headerFigure.setLineThickness(lineThickness);
	}

	/**
	 * {@inheritDoc}
	 */
	public void setfigureFont(String font) {
		headerFigure.setfigureFont(font);
	}
	
	/**
	 * UML Package header figure. this is a simple node figure.
	 */
	class UMLPackageHeaderFigure extends NodeFigure {

		/**
		 * Creates a new UMLPackageHeaderFigure.
		 */
		public UMLPackageHeaderFigure() {
			super();
			Debug.debug(this,"  Call UMLPackageHeaderFigure", debugChannel);
			final ToolbarLayout layout = new ToolbarLayout();
			layout.setSpacing(0);
			setLayoutManager(layout);
			setOpaque(true); // non-transparent figure

			// should look in the preferences
			setBorder(new LineBorder(ColorConstants.black));
			setBackgroundColor(ColorConstants.yellow);
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public void setBounds(Rectangle rect) {
			int stereoWidth = 0;
			int qualifWidth = 0;

			int headerHeight = getNameLabel().getPreferredSize().height + 4;
			int headerWidth  = getNameLabel().getPreferredSize().width;

			// Calculate height. Warning, must check if an icon is set on the element
			if (getIconLabel() != null && getIconLabel().getIcon()!= null) {
				headerHeight = headerHeight + getIconLabel().getPreferredSize().height;
			}
			if (getStereotypesLabel() != null) {
				headerHeight = headerHeight + getStereotypesLabel().getPreferredSize().height;
				stereoWidth  = getStereotypesLabel().getPreferredSize().width;
			}
			if (getQualifiedNameLabel() != null) {
				headerHeight = headerHeight + getQualifiedNameLabel().getPreferredSize().height;
				qualifWidth  = getQualifiedNameLabel().getPreferredSize().width;
			}

			// Calculate width
			if (stereoWidth > headerWidth) {
				headerWidth = stereoWidth;
			}
			if  (qualifWidth > headerWidth) {
				headerWidth = qualifWidth;
			}

			Rectangle headerRect = new Rectangle();
			headerRect.setLocation(0, 0);
			headerRect.setSize(headerWidth + 10, headerHeight);
			super.setBounds(headerRect);

			Debug.debug(this," bounds are : " +getBounds(), debugChannel);
		}
	}

	/**
	 * display the content of the package
	 * *.
	 */
	class UMLPackageContentFigure extends Figure {

		/** pane where the content of the element is draw */
		protected final IFigure pane;

		/** Scroll pane that manages the pane */
		protected ScrollPane scrollpane;

		/**
		 * Creates a new UMLPackageContentFigure.
		 */
		public UMLPackageContentFigure() {
			super();
			Debug.debug(this,"  Call UMLPackageContentFigure", debugChannel);

			// Set content layout
			setLayoutManager(new StackLayout());

			// Add pane for content
			pane = new FreeformLayer();
			pane.setLayoutManager(new FreeformLayout());

			// Add scrollpane
			ScrollPane scrollpane = new ScrollPane();
			scrollpane.setViewport(new FreeformViewport());
			scrollpane.setContents(pane);
			this.add(pane);

			// Set colors
			setBackgroundColor(headerFigure.getBackgroundColor());
			setBorder(new LineBorder(headerFigure.getBorderColor()));
			setOpaque(true);
		}

		/**
		 * Returns the content pane of this figure
		 * @return the content pane of this figure
		 */
		public IFigure getContentPane() {
			return pane;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public void setBounds(Rectangle rect) {
			int contentHeight = 0;
			// Father dimension
			int fatherHeight = getParent().getBounds().height;
			int fatherWidth  = getParent().getBounds().width;
			int headerY      = headerFigure.getSize().height;
			contentHeight=fatherHeight-headerY;
			super.setBounds(new Rectangle(0, headerY-1, fatherWidth, contentHeight));
			Debug.debug(this," bounds are : " +getBounds(), debugChannel);
		}
	}
}
